package application;

import javafx.scene.Cursor;
import javafx.scene.control.TextField;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

import Basics.Atom;
import Basics.Constant;
import Basics.MemDB;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyEvent;

public class InputScreenController implements Initializable, ControlledScreen 
{
	ScreensController myController; 
	
	@FXML
	TableView<GenTwitterObj> TweetTable;
	
	@FXML
	private TableColumn<GenTwitterObj, String> tweetUserCol;
	
	@FXML
	private TableColumn<GenTwitterObj, String> tweetMessageCol;
	
	@FXML
	TableView<GenTwitterObj> FollowsTable;
	
	@FXML
	private TableColumn<GenTwitterObj, String> followsFollowerCol;
	
	@FXML
	private TableColumn<GenTwitterObj, String> followsFollowedCol;
	
	@FXML
	TableView<GenTwitterObj> NumFollowersTable;
	
	@FXML
	private TableColumn<GenTwitterObj, String> numFollowersUserCol;
	
	@FXML
	private TableColumn<GenTwitterObj, String> numFollowersNumCol;
	
	@FXML
	TableView<GenTwitterObj> InterestTable;
	
	@FXML
	private TableColumn<GenTwitterObj, String> interestUserCol;
	
	@FXML
	private TableColumn<GenTwitterObj, String> interestSubjectCol;
	
	@FXML
	private Label transitive;
	
	@FXML
	private Label labelDealsWith;
	
	@FXML
	private Label labelExport;
	
	@FXML
	private Button generateProv;
	
	@FXML
	private Button eval;
	
	@FXML
	private Button downloadTweets;
	
	@FXML
	private TextArea userField;
	
	@FXML
	private TextField kField;
	
	@FXML
	private TextField nameField;
	
	@FXML
	private RadioButton user;
	
	@FXML
	private RadioButton admin;
	
	private final ObservableList<GenTwitterObj> tweetTlb = FXCollections.observableArrayList( FillTable("tweet") );
	
	private final ObservableList<GenTwitterObj> folllowerTlb = FXCollections.observableArrayList( FillTable("follows") );
	
	private final ObservableList<GenTwitterObj> interestTlb = FXCollections.observableArrayList( FillTable("isInterestedIn") );
	
	private final ObservableList<GenTwitterObj> numFollowersTlb = FXCollections.observableArrayList( FillTable("numFollowers") );
	

	
	public void initialize(URL fxmlFileLocation, ResourceBundle resources) 
	{
		tweetUserCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop1"));
		tweetMessageCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop2"));
		TweetTable.setItems(tweetTlb);
		
		followsFollowerCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop1"));
		followsFollowedCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop2"));
		FollowsTable.setItems(folllowerTlb);
		
		numFollowersUserCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop1"));
		numFollowersNumCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop2"));
		NumFollowersTable.setItems(numFollowersTlb);
		
		interestUserCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop1"));
		interestSubjectCol.setCellValueFactory(new PropertyValueFactory<GenTwitterObj, String>("prop2"));
		InterestTable.setItems(interestTlb);
		
		eval.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() 
	           { 
					@Override
					public void handle(ActionEvent t) 
					{
						Evaluate(t);
					}
	           });
		
		kField.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() 
				{
					public void handle(final KeyEvent keyEvent) 
					{
						SetEvalButtonMode(keyEvent);
					}
                });
		
		downloadTweets.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>()
				{
					@Override
					public void handle(ActionEvent t) 
					{
						try 
						{
							downloadTweets(userField.getText());
							userField.setText("");
						} 
						catch (NumberFormatException e) 
						{
							e.printStackTrace();
						} 
						catch (IOException e) 
						{
							e.printStackTrace();
						}
						
					}
				});
		
		user.setOnAction(new EventHandler<ActionEvent>() 
				{ 
					@Override 
					public void handle(ActionEvent e) 
					{ 
						nameField.setEditable(true);
					} 
				});
		
		admin.setOnAction(new EventHandler<ActionEvent>() 
				{ 
					@Override 
					public void handle(ActionEvent e) 
					{
						nameField.setText("");
						nameField.setEditable(false);
					} 
				});
	}

	
	
	public void setScreenParent(ScreensController screenParent)
	{ 
		myController = screenParent; 
	}

	
	
	private void SetEvalButtonMode (KeyEvent keyEvent)
	{
		if (true == isNumeric(keyEvent.getText()))
			eval.setDisable(false);
		else
			eval.setDisable(true);
	}
	
	
	
	private void Evaluate (ActionEvent event)
	{
		try 
		{
			/*if (true == isNumeric(kField.getText()))
			{*/
				GraphScreenController.evaluate(Integer.parseInt(kField.getText()), nameField.getText());
				kField.setText("");
			//}
		}
		
		catch (NumberFormatException e) 
		{
			e.printStackTrace();
		}
	}
	

	
	private void downloadTweets (String user) throws NumberFormatException, IOException
	{		
		myController.setCursor(Cursor.WAIT);
		dowloadInfo(user, "tester_tweets");
		dowloadInfo(user, "tester_followers");
		genNewStats(user, "tweet", "tweets", TweetTable, 2, false, tweetUserCol, tweetMessageCol);
		genNewStats(user, "follows", "numfollowers", FollowsTable, 0, false, followsFollowerCol, followsFollowedCol);
		genNewStats(user, "numfollowers", "numfollowers", NumFollowersTable, 1, true, numFollowersUserCol, numFollowersNumCol);
		myController.setCursor(Cursor.DEFAULT);
		//refreshTableView(InterestTable, Arrays.asList(interestUserCol, interestSubjectCol), newRows);
	}

	
	
	private void dowloadInfo (String user, String script) throws NumberFormatException, IOException
	{
		ProcessBuilder pb = new ProcessBuilder("C:\\Python34\\python.exe","C:\\Users\\amirgilad\\WORKSPACE\\TwitterAnalyzer\\" + script + ".py", user);
		Process p = pb.start();
		 
		BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
		String line;

		while ((line = in.readLine()) != null) 
		{
		  System.out.println(line);
		}
	}
	
	
	
	private void genNewStats (String user, String type, String tableName, TableView<GenTwitterObj> table, int idx, boolean isNumFol, TableColumn<GenTwitterObj, String> ... cols) throws NumberFormatException, IOException
	{
		List<GenTwitterObj> newRows = new ArrayList<GenTwitterObj>();
		if (isNumFol) 
		{
			int i = 0;
			//String [] subjects = Initializer.makeData(50, 99999, 10000);
			String [] subjects = Initializer.makeDemoData(25);
			List<GenTwitterObj> interestedRows = new ArrayList<GenTwitterObj>();
			Map<String, String> vals = parseCSVTwoParams(user, tableName, 0, 1);
			for (Map.Entry<String, String> entry : vals.entrySet()) 
			{
				newRows.add(new GenTwitterObj(entry.getKey(), entry.getValue()));
				interestedRows.add(new GenTwitterObj(entry.getKey(), subjects[i++]));
				MemDB.getInstance().InsertToTable(type, Arrays.asList(entry.getKey(), entry.getValue()));
				MemDB.getInstance().InsertToTable("isInterestedIn", Arrays.asList(entry.getKey(), subjects[i++]));
			}
			
			refreshTableView(InterestTable, Arrays.asList(interestUserCol, interestSubjectCol), interestedRows);
		}
		
		else
		{
			List<String> vals = parseCSV(user, tableName, idx);
			for (String msg : vals) 
			{
				newRows.add(new GenTwitterObj(user, msg));
				MemDB.getInstance().InsertToTable(type, Arrays.asList(user, msg));
			}
		}
		
		refreshTableView(table, Arrays.asList(cols), newRows);
	}
	
	
	
	private <T,U> void refreshTableView(TableView<T> tableView, List<TableColumn<T,U>> columns, List<T> rows) 
	{        
	    tableView.getColumns().clear();
	    tableView.getColumns().addAll(columns);

	    ObservableList<T> list = FXCollections.observableArrayList(rows);
	    tableView.setItems(list);
	}
	
	
	 
	private List<String> parseCSV (String user, String type, int idx)
	{
		String csvFile = "C:\\Users\\amirgilad\\WORKSPACE\\TwitterAnalyzer\\" + user + "_" + type + ".csv";
		BufferedReader br = null;
		String line = "";
		String cvsSplitBy = ",";
		List<String> tweets = new ArrayList<String>();
		try 
		{
			br = new BufferedReader(new FileReader(csvFile));
			while ((line = br.readLine()) != null) 
			{
			    // use comma as separator
				String[] fileLine = line.split(cvsSplitBy);
				if (false == line.equals("") && false == line.contains("text") && false == line.contains("user") && false == line.equals(",,")) 
				{
					tweets.add(fileLine[idx].replaceAll("^\"|\"$", ""));
				}
			}
		}
	 
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		} 
		finally 
		{
			if (br != null) 
			{
				try 
				{
					br.close();
				} 
				catch (IOException e) 
				{
					e.printStackTrace();
				}
			}
		}
		
		System.out.println("Done");
		return tweets;
	}
	
	
	
	private Map<String, String> parseCSVTwoParams (String user, String type, int idx1, int idx2)
	{
		String csvFile = "C:\\Users\\amirgilad\\WORKSPACE\\TwitterAnalyzer\\" + user + "_" + type + ".csv";
		BufferedReader br = null;
		String line = "";
		String cvsSplitBy = ",";
		Map<String, String> followers = new HashMap<String, String>();
		try 
		{
			br = new BufferedReader(new FileReader(csvFile));
			while ((line = br.readLine()) != null) 
			{
			    // use comma as separator
				String[] fileLine = line.split(cvsSplitBy);
				//System.out.println(line);
				if (false == line.equals("") && false == line.contains("text") && false == line.contains("user")) 
				{
					followers.put(fileLine[idx1], fileLine[idx2]);
				}
			}
		}
	 
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		} 
		finally 
		{
			if (br != null) 
			{
				try 
				{
					br.close();
				} 
				catch (IOException e) 
				{
					e.printStackTrace();
				}
			}
		}
		
		//System.out.println("Done");
		return followers;
	}
	
	
	private List<GenTwitterObj> FillTable (String atomName)
	{
		List<GenTwitterObj> retVal = new ArrayList<GenTwitterObj>();
		if (null != MemDB.getInstance().getFacts().get(atomName))
		{
			for (Atom atom : MemDB.getInstance().getFacts().get(atomName)) 
			{
				retVal.add( new GenTwitterObj(atom.getParams().get(0).getName(), atom.getParams().get(1).getName()) );
			}
		}
		
		return retVal;
	}
	
	
	
	private boolean isNumeric(String str)  
	{  
		try  
		{  
			double d = Double.parseDouble(str);  
		}  
		catch(NumberFormatException nfe)  
		{  
			return false;  
		}  
		return true;  
	}

 
}
